#include <allegro.h>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define NUM_SIDES 6
#define Y_HEIGHT 76
#define X_WIDTH 66
#define PLAYSPACE_W 758
#define PLAYSPACE_H 696

//-------------------------------------DECLARATIONS-----------------------

int level;
void init();


struct hex{
    int init_sides[NUM_SIDES];              /** initial static/base hex, 6 sides of colors(int) -- does not change */
    int working_sides[NUM_SIDES];           /** working hex -- any mods to the hex structure done with this */
    char sidesfilename[NUM_SIDES][10];      /** each side has a triangle bitmap(10 chars long filename) */
    BITMAP *hex_bmp;
    BITMAP *hex_buf;                        /** the final composed bitmap */
    int hex_id;
    int hex_score;
};


BITMAP  *sides_bmp[NUM_SIDES];              /** temporary array of bitmap sides - load "sidesfilename" into this */
BITMAP  *background;                        /** the background board-image */
BITMAP  *playspace;                         /** the motion/playspace (move mouse/rotate here) */
BITMAP  *buffer;                            /** double buffer */
BITMAP  *timer_buf;
BITMAP  *timer[10];
BITMAP  *hex_shadow;
BITMAP  *drop_piece;
BITMAP  *right_lay;

SAMPLE  *drop_sound;
SAMPLE  *tick_sound;


hex* gen_hex(int level);

void rotate_hex(hex*);
void deinit(hex*);
void debug_info(hex*);
void draw_screen(BITMAP*, BITMAP*, BITMAP*, hex*);
void h_timer(BITMAP*, int x, int y, int width, int height);
void place_shadow(BITMAP* hex_shadow, BITMAP*, hex*);

int grid_x();
int grid_y();

volatile int sticks=6;
static int hex_num = 0;
static int last_sticks = 0;
static int base_score = 0;
static int grid[11][9][6];

void Seconds_Tick(void)
{   if(sticks<=0){
        sticks = 9;
    }
    else sticks--;
}
END_OF_FUNCTION(Seconds_Tick);

//---------------------------------------MAIN FUNCTION-------------------

int main() {
    init();
    int level = 6;
    int x = grid_x();
    int y = grid_y();

    hex* h = gen_hex(level);

    while (!key[KEY_ESC]) {
        h->hex_score = sticks;

        rotate_hex(h);

        if(mouse_b & 1) {
            if (sticks == 0) {
                timer_buf = timer[0];
            } else timer_buf = timer[sticks];

            masked_blit(playspace, drop_piece, mouse_x, mouse_y, 0, 0, 100, 100); //buffer->w, buffer->h);
            play_sample(drop_sound, 255, 128, 1000, 0);
            place_shadow(drop_piece, background, h);

            base_score += h->hex_score;

            rest(100);
            free(h);
            install_int_ex(&Seconds_Tick, SECS_TO_TIMER(1));
            h = gen_hex(level);
            last_sticks = sticks;
        }

        if(last_sticks != sticks) {
            play_sample(tick_sound, 255, 128, 1000, 0);
            last_sticks = sticks;
        }

        if(sticks == 0) {
            remove_int(&Seconds_Tick);
            timer_buf = timer[0];
        }

/*
        if(sticks == 0) {

//            free(h);
//            h = gen_hex(level);
        }
*/
        debug_info(h);
        draw_screen(background, buffer, playspace, h);
    }
    deinit(h);
    return 0;
}
END_OF_MAIN()


//---------------------------------------INIT FUNCTION--------------------------
void init() {
	int depth, res;
    srand (time(NULL));
	allegro_init();
    hex h;
	if (desktop_color_depth() == 0) {
        depth = 16;
	}
	set_color_depth(16);
	res = set_gfx_mode(GFX_AUTODETECT_FULLSCREEN, 1024, 768, 0, 0);

	if (res != 0) {
		allegro_message(allegro_error);
		exit(-1);
	}
	install_timer();
	install_keyboard();
	install_mouse();
    if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0){
        allegro_message("Error initing sound");
    }

	LOCK_VARIABLE(sticks);
    LOCK_FUNCTION(Seconds_Tick);
    install_int_ex(&Seconds_Tick, SECS_TO_TIMER(1));

    /* add other initializations here */
    show_mouse(NULL);
    set_mouse_range(0, 0, 660, 608);
    background = load_bitmap("hexbg5.bmp", NULL);
    right_lay = load_bitmap("rightlay.bmp", NULL);
    hex_shadow = load_bitmap("hexshad2.bmp", NULL);
    buffer = create_bitmap(SCREEN_W, SCREEN_H);

    playspace = create_bitmap(SCREEN_W, SCREEN_H);
    timer_buf = create_bitmap(80, 80);
    drop_piece = create_bitmap(100, 100);

    drop_sound = load_sample("bell-octave1.wav");
    tick_sound = load_sample("tabla-hi-na.wav");

    if(!drop_sound || !tick_sound){
        allegro_message("Error reading wav");
    }


    clear_to_color(buffer, makecol(255, 0, 255));
    clear_to_color(playspace, makecol(255, 0, 255));
    clear_to_color(timer_buf, makecol(255, 0, 255));
    clear_to_color(drop_piece, makecol(255, 0, 255));

    timer[0]=load_bitmap("timer0.bmp",NULL);
    timer[1]=load_bitmap("timer1.bmp",NULL);
    timer[2]=load_bitmap("timer2.bmp",NULL);
    timer[3]=load_bitmap("timer3.bmp",NULL);
    timer[4]=load_bitmap("timer4.bmp",NULL);
    timer[5]=load_bitmap("timer5.bmp",NULL);
    timer[6]=load_bitmap("timer6.bmp",NULL);
    timer[7]=load_bitmap("timer7.bmp",NULL);
    timer[8]=load_bitmap("timer8.bmp",NULL);
    timer[9]=load_bitmap("timer9.bmp",NULL);

    for (int x = 0; x<11; x++){
        for (int y = 0; y<9; y++){
            for (int h = 0; h<6; h++){
                grid[x][y][h] = 0;
            }
        }
    };
}


//---------------------------------------DE-INIT FUNCTION-----------------------
void deinit(hex* h) {
	clear_keybuf();
	/* add other dinitializations here */
	destroy_bitmap(h->hex_bmp);
	destroy_bitmap(h->hex_buf);
	destroy_bitmap(background);
	for(int i=0; i<6; i++){
        destroy_bitmap(sides_bmp[i]);
    }
	destroy_bitmap(buffer);
    destroy_bitmap(drop_piece);
	destroy_bitmap(hex_shadow);
    destroy_sample(drop_sound);
    destroy_sample(tick_sound);
    remove_sound();

	free(h);
}


//---------------------------------------ROTATE_HEX FUNCTION-------------------

void rotate_hex(hex* h){
    int x;
// -- ROTATE INTERNAL STRUCTURE: Create offset index, use that for
// -- initial array position compared to current mouse-wheel value (modded by 6)
// -- then assign the initial array from offset to the "working array"
    int position = abs(mouse_z%NUM_SIDES);

    if (mouse_z < 0) position = NUM_SIDES - position;

    for (int i=0; i < 6; i++) {
        if (position % 6 == 0) {
            position = 0;
        }
		h->working_sides[i] = h->init_sides[position];
		position++;
    }
    rotate_sprite(playspace, h->hex_buf, mouse_x, mouse_y, ftofix(-(position*60.0*.711)));
    masked_blit(timer[sticks], playspace, 0, 0, mouse_x+30, mouse_y+30, 100, 100);
}


//-------------------------------GEN_HEX FUNCTION-------------------------------

hex* gen_hex(int level) {
    char strbuf[10];
    hex* h = (hex*)malloc(sizeof(hex));
                                                                                //CREATE HEXAGON STRUCTURE...
    for(int i=0; i<6; i++){
        h->init_sides[i] = (rand()%(level+1))+1;                            /** init the initial hex array... */
        h->working_sides[i] = h->init_sides[i];                         /** and the working array */

        snprintf(strbuf, 10, "hex%d%d.bmp", i, h->init_sides[i]);       /** create filename for each bitmap sides in hex */
        strcpy(h->sidesfilename[i], strbuf);                            /** copy those filenames to the sidesfilename */
        sides_bmp[i] = load_bitmap(h->sidesfilename[i],NULL);           /** load those bitmap files into array */
    }
    h->hex_id = hex_num;
    h->hex_bmp = create_bitmap(100, 100);                               /** create a bitmap to hold the hexagon */
    clear_to_color(h->hex_bmp, makecol(255, 0, 255));
    h->hex_buf = create_bitmap(100, 100);
    clear_to_color(h->hex_buf, makecol(255, 0, 255));                   /** and make it transparent... */

    sticks = 9;                                                         /** create max_timer */
    for(int i=0;i<6;i++){
        masked_blit(sides_bmp[i], h->hex_bmp, 0, 0, 0, 0, 100, 100);    /** blit all the sides_bmp to the hexagon struct */
    }
    masked_blit(h->hex_bmp, h->hex_buf, 0, 0, 0, 0, 100, 100);
    hex_num++;
    return h;

}


int grid_x() {
    return ((mouse_x+(X_WIDTH)/2)/X_WIDTH)%X_WIDTH;
}

int grid_y() {
    return ((mouse_y+38)/Y_HEIGHT)%Y_HEIGHT;
    //return int((mouse_y+38)/76);
}

int grid_y2() {
    return ((mouse_y+19)/Y_HEIGHT)%Y_HEIGHT;
    //return int((mouse_y+76)/76);
}

void place_shadow(BITMAP* hex_shadow, BITMAP* buffer, hex* h) {
    int x = grid_x();
    int y = grid_y();
    int y2 = grid_y2();
    if (grid_x() % 2) {
        masked_blit(hex_shadow, buffer, 0, 0, grid_x()*X_WIDTH, grid_y2()*Y_HEIGHT+38, 100, 100);
        for(int i=0;i<6;i++){
          grid[x][y2][i] = h->working_sides[i];                                    /** TODO: put hex in grid */
        }
    }
    else {
        masked_blit(hex_shadow, buffer, 0, 0, grid_x()*X_WIDTH, grid_y()*Y_HEIGHT, 100, 100);
        for(int i=0;i<6;i++){
          grid[x][y][i] = h->working_sides[i];                                    /** TODO: put hex in grid */
        }
    }
}

void debug_info(hex* h){
    //  Debugging info printed to screen...
    textprintf_ex(playspace, font, 800, 50,  makecol(255, 255, 255), -1, "Mouse Z Value: %d", mouse_z);
    textprintf_ex(playspace, font, 800, 75,  makecol(255, 255, 255), -1, "Side 0: %d", h->working_sides[0]);
    textprintf_ex(playspace, font, 800, 100, makecol(255, 255, 255), -1, "Side 1: %d", h->working_sides[1]);
    textprintf_ex(playspace, font, 800, 125, makecol(255, 255, 255), -1, "Side 2: %d", h->working_sides[2]);
    textprintf_ex(playspace, font, 800, 150, makecol(255, 255, 255), -1, "Side 3: %d", h->working_sides[3]);
    textprintf_ex(playspace, font, 800, 175, makecol(255, 255, 255), -1, "Side 4: %d", h->working_sides[4]);
    textprintf_ex(playspace, font, 800, 200, makecol(255, 255, 255), -1, "Side 5: %d", h->working_sides[5]);
    textprintf_ex(playspace, font, 800, 225, makecol(255, 255, 255), -1, "Hex_Num: %d", hex_num);
    textprintf_ex(playspace, font, 800, 250, makecol(255, 255, 255), -1, "grid x: %d", grid_x());
    textprintf_ex(playspace, font, 800, 275, makecol(255, 255, 255), -1, "grid y: %d", grid_y());
    textprintf_ex(playspace, font, 800, 290, makecol(255, 255, 255), -1, "grid y2: %d", grid_y2());
    textprintf_ex(playspace, font, 800, 300, makecol(255, 255, 255), -1, "sticks: %d", sticks);
    textprintf_ex(playspace, font, 800, 325, makecol(255, 255, 255), -1, "Hex_Score: %d", h->hex_score);
    textprintf_ex(playspace, font, 800, 350, makecol(255, 255, 255), -1, "Base_Scores: %d", base_score);
    textprintf_ex(playspace, font, 800, 375, makecol(255, 255, 255), -1, "0, 0, 0: %d", grid[0][0][0]);
    textprintf_ex(playspace, font, 800, 400, makecol(255, 255, 255), -1, "mouse_x: %d", mouse_x);
    textprintf_ex(playspace, font, 800, 425, makecol(255, 255, 255), -1, "mouse_y: %d", mouse_y);
    textprintf_ex(playspace, font, 800, 450, makecol(255, 255, 255), -1, "mouse_r: awesome", grid[0][0][0]);
}

void draw_screen(BITMAP* background, BITMAP* buffer, BITMAP* playspace, hex* h){
    blit(background, buffer, 0, 0, 0, 0, buffer->w, buffer->h);
    place_shadow(hex_shadow, buffer, h);
    masked_blit(playspace, buffer, 0, 0, 0, 0, buffer->w, buffer->h);
    masked_blit(buffer, screen, 0, 0, 0, 0, buffer->w, buffer->h);
    clear_to_color(playspace, makecol(255, 0, 255));
}
